package cn.com.aiouyi.shiro;

import java.util.Date;

import javax.annotation.Resource;

import org.apache.commons.lang3.time.DateUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import cn.com.aiouyi.common.Setting;
import cn.com.aiouyi.entity.Member;
import cn.com.aiouyi.service.MemberService;
import cn.com.aiouyi.util.SystemUtils;

/**
 * 权限认证
 * 
 * @author hanson
 */
public class AuthenticationRealm extends AuthorizingRealm {

	@Resource(name = "memberServiceImpl")
	private MemberService memberService;
	
	/**
	 * 获取认证信息
	 * @param token 令牌
	 * @return 认证信息
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken token) {
		AuthenticationToken authenticationToken = (AuthenticationToken) token;
		String username = authenticationToken.getUsername();
		String enPassword = authenticationToken.getPassword() == null ? null : new String(authenticationToken.getPassword());
		Principal.Type type = authenticationToken.getType();
		/*AuthenticationToken.Way way = authenticationToken.getWay();
		String captchaId = authenticationToken.getCaptchaId();
		String captcha = authenticationToken.getCaptcha();*/
		String ip = authenticationToken.getHost();
		
		if (username != null && enPassword != null) {
			if (type == Principal.Type.admin) {
				Member member = memberService.findByUsername(username);
				if(member == null){
					throw new UnknownAccountException();
				}
				if (!member.getIsEnabled()) {
					throw new DisabledAccountException();
				}
				Setting setting = SystemUtils.getSetting();
				if (member.getIsLocked()) {
						int loginFailureLockTime = setting.getAccountLockTime();
						if (loginFailureLockTime == 0) {
							throw new LockedAccountException();
						}
						Date lockedDate = member.getLockedDate();
						Date unlockDate = DateUtils.addMinutes(lockedDate, loginFailureLockTime);
						if (new Date().after(unlockDate)) {
							member.setLoginFailureCount(0);
							member.setIsLocked(false);
							member.setLockedDate(null);
							//memberService.updateIncludeProperties(member, new String[]{"isLocked", "LockedDate", "loginFailureCount", "lastLoginIp", "lastLoginDate"});
						} else {
							throw new LockedAccountException();
						}
				}
				if (!enPassword.equals(member.getPassword())) {
					int loginFailureCount = member.getLoginFailureCount() + 1;
					if (loginFailureCount >= setting.getAccountLockCount()) {
						member.setIsLocked(true);
						member.setLockedDate(new Date());
					}
					member.setLoginFailureCount(loginFailureCount);
					//memberService.updateIncludeProperties(member, new String[]{"isLocked", "LockedDate", "loginFailureCount", "lastLoginIp", "lastLoginDate"});
					throw new IncorrectCredentialsException();
				}
				member.setLastLoginIp(ip);
				member.setLastLoginDate(new Date());
				member.setLoginFailureCount(0);
				//memberService.updateIncludeProperties(member, new String[]{"isLocked", "LockedDate", "loginFailureCount", "lastLoginIp", "lastLoginDate"});
				return new SimpleAuthenticationInfo(new Principal(member.getId(), member.getUsername(), member.getPassword(), type), enPassword, getName());
			} else {
				throw new UnknownAccountException();
			}
		}
		throw new UnknownAccountException();
	}

	/**
	 * 获取授权信息
	 * @param principalCollection
	 * @return 授权信息
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
		/*Principal principal = (Principal) principalCollection.fromRealm(getName()).iterator().next();
		if (principal != null) {
			Set<String> authorities = new HashSet<String>();
			List<Permission> permissions = memberService.findPermissions(principal.getId());
			permissions.forEach((p) -> {
				authorities.add(p.getPermCode());
			});
			if (authorities != null) {
				SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
				authorizationInfo.addStringPermissions(authorities);
				return authorizationInfo;
			}
		}*/
		return null;
	}

}